const std = @import("std");
const jetzig = @import("jetzig");
const user_service = @import("../../service/user_service.zig");
const const_val = @import("../../utils/const_value.zig");
const myjwt = @import("../../utils/myjwt.zig");

/// 登录页
pub fn index(req: *jetzig.Request) !jetzig.View {
    return req.render(.ok);
}

/// 接收登录请求数据
const LoginPost = struct {
    username: []const u8,
    password: []const u8,
};

/// 提交登录
pub fn post(req: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
    const body = req.body;
    std.debug.print("登录post提交进来了\n", .{});
    std.debug.print("login post data: {s}\n", .{body});
    if (body.len == 0) {
        return req.fail(.bad_request);
    }

    const post_data = try std.json.parseFromSlice(LoginPost, std.heap.page_allocator, body, .{});
    const post_user = post_data.value;

    const user_info = try user_service.getUserByUsername(post_user.username);

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    var allocator = gpa.allocator();

    if (user_info) |db_user| {
        // 计算哈希值
        var out: [32]u8 = undefined;
        const salt_pdw = try std.fmt.allocPrint(allocator, "{s}{s}", .{ post_user.password, const_val.PASSWORD_SALT });
        defer allocator.free(salt_pdw);
        std.crypto.hash.sha2.Sha256.hash(salt_pdw, &out, .{});
        const hashed_password = try std.fmt.allocPrint(allocator, "{s}", .{std.fmt.fmtSliceHexLower(&out)});
        defer allocator.free(hashed_password);
        // std.debug.print("hashed login post user password: {s}\n", .{hashed_password});

        // 将哈希结果与数据库的密码进行比较
        if (!std.mem.eql(u8, hashed_password, db_user.password)) {
            var root = try data.object();
            try root.put("code", 401);
            try root.put("msg", "用户名或密码错误");
            try root.put("data", null);
            return req.fail(.unauthorized);
        }

        // 生成token
        const payload = myjwt.GenPayload{
            .iss = const_val.JWT_ISS,
            .sub = const_val.JWT_SUB,
            .exp = std.time.timestamp() + const_val.JWT_EXP_TIME,
            .username = db_user.username,
        };
        const token = myjwt.generateToken(payload) catch "";
        // std.debug.print("generate token: {s}\n", .{token});
        if (token.len == 0) {
            var root = try data.object();
            try root.put("code", 500);
            try root.put("msg", "服务器内部错误");
            try root.put("data", null);
            return req.fail(.internal_server_error);
        }

        var root = try data.object();
        try root.put("code", 200);
        try root.put("msg", "用户名或密码错误");

        var data_obj = try data.object();
        try data_obj.put("username", post_user.username);
        try data_obj.put("nickname", db_user.nickname);
        try data_obj.put("token", token);
        try root.put("data", data_obj);

        return req.render(.ok);
    } else {
        var root = try data.object();
        try root.put("code", 401);
        try root.put("msg", "用户名或密码错误");
        try root.put("data", null);
        return req.fail(.unauthorized);
    }
}
